package com.example.thread;

// 这个和类 MultithreadingAlternatingPrinting 中演示的题是一样的题。
// 可能对于MultithreadingAlternatingPrinting类展示的写法，有些初学者会心有疑惑，因为他没了解过 ReentrantLock、Lock 、Condition ，就觉得这个看了不踏实。
// 所以，在下面这个类中，我们用synchronized 配合 wait() 和 notifyAll 也是一样的。思路是一样的。具体的使用锁的方式、等待、唤醒的api不一样而已。
public class MultithreadingAlternatingPrinting02 {
    private volatile int COUNT_NUM = 1;
    private volatile String CODE = "A";
    private static int oneTimes = 34;
    private static int othersTimes = 33;

    void onePrint() {
        synchronized (this) {
            while(!CODE.equals("A")) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM);
            COUNT_NUM++;
            CODE = "B";
            notifyAll();
        }
    }
    void twoPrint() {
        synchronized (this) {
            while(!CODE.equals("B")) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM);
            COUNT_NUM++;
            CODE = "C";
            notifyAll();
        }
    }
    void threePrint() {
        synchronized (this) {
            while(!CODE.equals("C")) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + ": " + COUNT_NUM);
            COUNT_NUM++;
            CODE = "A";
            notifyAll();
        }
    }

    public static void main(String[] args) {
        MultithreadingAlternatingPrinting02 printNumber = new MultithreadingAlternatingPrinting02();
        new Thread(() -> {
            for (int i = 0; i < oneTimes; i++) {
                printNumber.onePrint();
            }
        },"线程A").start();

        new Thread(() -> {
            for (int i = 0; i < othersTimes; i++) {
                printNumber.twoPrint();
            }
        },"线程B").start();

        new Thread(() -> {
            for (int i = 0; i < othersTimes; i++) {
                printNumber.threePrint();
            }
        },"线程C").start();
    }
}
